#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include "render_util.h"
#include "interface.h"


void display_init(DisplayUtilState* state, GameInterface* interface) {
    state->interface = interface;
    state->cur_sprite = 0;
    state->flip_x = 0;
    state->flip_y = 0;
    state->palette = 0;

    // reset sprites
    for (int i = 0; i < MAX_SPRITES; i++) {
        memset(&interface->display_info.sprites[i], 0, sizeof(Sprite));
    }
}

void display_clear_row(DisplayUtilState* state, int row) {
    DisplayInfo* display = &state->interface->display_info;

    for (int x = 0; x < TILE_WIDTH; x++) {
        display->tiles[x][row] = 255;    
    }
}

void display_clear_rect(DisplayUtilState* state, int x, int y, int w, int h) {
    DisplayInfo* display = &state->interface->display_info;

    for (int r = y; r < y + h; r++) {
        for (int c = x; c < x + w; c++) {
            display->tiles[c][r] = 255;
        }
    }
}

void clear_display(DisplayUtilState* state) {
    DisplayInfo* display = &state->interface->display_info;
    memset(display->tiles, 255, sizeof(display->tiles));
    memset(display->tile_palettes, 0, sizeof(display->tile_palettes));
}

void display_text(DisplayUtilState* state, int x, int y, const char* fmt, ...) {
    char buf[64];
    int left = x;

    va_list args;
    va_start(args, fmt);
    vsprintf(buf, fmt, args);
    va_end(args);

    DisplayInfo* display = &state->interface->display_info;
    for (int i = 0; buf[i] != '\0'; i++) {
        if (buf[i] == '\n') {
            x = left;
            y++;
            continue;
        }

        int gfx = 64; // space

        if (buf[i] != ' ') {
            if (buf[i] >= 'a' && buf[i] <= 'z') {
                gfx = 65 + (buf[i] - 'a');
            }
            else if (buf[i] >= 'A' && buf[i] <= 'Z') {
                gfx = 65 + (buf[i] - 'A');
            }
            else if (buf[i] >= '0' && buf[i] <= '9') {
                gfx = 48 + (buf[i] - '0');
            }
            else {
                // specific characters
                switch (buf[i]) {
                    case '/':
                        gfx = 58;
                        break;

                    case '-':
                        gfx = 59;
                        break;

                    case '!':
                        gfx = 91;
                        break;

                    case '.':
                        gfx = 37;
                        break;

                    case '"':
                    case '\'':
                        gfx = 38;
                        break;
                }
            }
        }

        if (x >= 0 && y >= 0 && x < TILE_WIDTH && y < TILE_HEIGHT) {
            display->tiles[x][y] = gfx;
            display->tile_palettes[x][y] = state->palette;
        }

        x++;
    }
}

int display_sprite(DisplayUtilState* state, int x, int y, int sprite) {
    if (state->cur_sprite == MAX_SPRITES) return 1;

    DisplayInfo* display = &state->interface->display_info;
    Sprite* sprite_slot = &display->sprites[state->cur_sprite];

    sprite_slot->flags = SPRITE_ACTIVE;
    if (state->flip_x) sprite_slot->flags |= SPRITE_FLIP_X;
    if (state->flip_y) sprite_slot->flags |= SPRITE_FLIP_Y;
    sprite_slot->location_x = x;
    sprite_slot->location_y = y;
    sprite_slot->palette = state->palette;
    sprite_slot->sprite = sprite;

    state->cur_sprite++;
    return 0;
}